/**函数表达式 */
function greeter(fn: (a: string) => void) {
  fn("Hello, World!");
}

function printToConsole(s: string) {
  console.log(s)
}

type Callback = (a: string) => void;
function greeter2(fn: Callback) {
  fn("Hello, World!");
}
/**调用签名 */
type DescribableFunc = {
  desc: string;
  (arg: number): boolean
}
function doSomething(fn: DescribableFunc) {
  console.log(fn.desc + 'returned' + fn(6))
}

const myFunc = (arg: number) => arg > 3
myFunc.desc = 'This is my function';
doSomething(myFunc);

/**构造签名 */
type CallConstructor = {
  (n?: number): string;
  new(n: string): Date;
}

function fn(ctor: CallConstructor) {
  console.log(ctor(3))
  console.log(new ctor('2025/06/15'))
}

fn(Date)

/**泛型函数 */
function tFn<T>(arg: T[]): T {
 return arg[0]
}

console.log(tFn([1, 2, 3]))
console.log(tFn(['a', 'b', 'c']))
console.log(tFn([]))

// 多类型参数
function cMap<Input, Output>(arr: Input[], fn: (arg: Input) => Output): Output[] {
  return arr.map(fn)
}
console.log(cMap(['1', '2', '3'], (x) => +x * 2))

// 泛型约束
function longest<T extends {length: number}>(a: T, b: T) {
  if (a.length >= b.length) {
    return a
  } else {
    return b
  }
}

console.log(longest('11', '222'))
console.log(longest([1, 2], [1, 2, 3]))
// console.log(longest(10, 100)) // 报错：类型“number”的参数不能赋给类型“{ length: number; }”的参数
// IMPORTANT: 
// 1、请记住，泛型就是将两个或多个具有相同类型的值关联起来！
// 2、如果一个类型参数只出现在一个位置，强烈重新考虑是否真的需要它

/**重载函数 */

/**
 * IMPORTANT:
 * 1、从外部看不到实现的签名。在编写重载函数时，你应该始终在函数实现之上有两个或多个签名。
 * 2、尽可能使用联合类型的参数而不是重载
 */

/**this */
interface User {
  admin: boolean;
}
declare function getDB(): DB;
interface DB {
  filterUsers(filter: (this: User) => boolean): User[];
}
 
const db = getDB();
const admins = db.filterUsers(function (this: User) {
  return this.admin;
});

/**剩余形参 */
function multiply(n: number, ...m: number[]) {
  return m.map(x => n * x)
}

const aa = multiply(10, 1, 2, 3, 4);

/**剩余实参 */
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
arr1.push(...arr2);

// const args = [8, 5]; // 报错
const args = [8, 5] as const;
const angle = Math.atan2(...args);

/**参数解构 */
type AA = { a: number, b: number }
function sum({a, b}: AA) {
  return a + b;
}


type voidFunc = () => void;
 
const f1: voidFunc = () => {
  return true;
};
 
const f2: voidFunc = () => true;
 
const f3: voidFunc = function () {
  return true;
};

console.log(f1(), f2(), f3())

export {}